﻿using System.Linq;
using Admin.Core;
using Admin.Util;
using Admin.Web.Core.Handlers;
using Furion;
using Furion.FriendlyException;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using SqlSugar;

namespace Admin.Web.Core
{
    public class Startup : AppStartup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);

            services.AddCorsAccessor();

            services.AddControllers()
                    .AddInjectWithUnifyResult<RESTfulResultProvider>();

            services.AddSqlSugar(new ConnectionConfig
            {
                ConnectionString = App.Configuration["ConnectionStrings:AdminDbContext"],//连接符字串
                DbType = DbType.MySql,
                IsAutoCloseConnection = true,
                InitKeyType = InitKeyType.Attribute//从特性读取主键自增信息
            }, db =>
            {
                //输出请求sql到前端
                db.Aop.OnLogExecuting = (sql, pars) =>
                {
                    var sqlStr = sql + "\r\n" + db.Utilities.SerializeObject(pars.Select(x=>x.Value));
                    App.PrintToMiniProfiler("SqlSugar", "Info", sqlStr);
                };
                //错误Sql记录
                db.Aop.OnError = (error) =>
                {
                    if(App.Configuration["Serilog:SqlExecuteErrorToMySQL"] == "true")
                    {
                        var pars = error.Parametres as SugarParameter[];
                        var parsJson = db.Utilities.SerializeObject(pars.ToList().Select(x => x.Value)) ?? "";
                        throw Oops.Oh(SystemErrorCodes.s2404, $"{error.Sql} 参数:{parsJson}");
                    }
                };
                //审计日志
                db.Aop.OnDiffLogEvent = (it) =>
                {
                    if (App.Configuration["Serilog:WriteAuditsLog"] == "true")
                    {
                        var editBeforeData = db.Utilities.SerializeObject(it.BeforeData);
                        var editAfterData = db.Utilities.SerializeObject(it.AfterData);
                        var parsJson = db.Utilities.SerializeObject(it.Parameters.ToList().Select(x => x.Value)) ?? "";
                        var sysAudits = new SysAudits
                        {
                            Title = it.BusinessData.ToString(),
                            SqlContent = it.Sql.RemoveClean(),
                            Parameter = parsJson,
                            NewValue = editBeforeData,
                            OldValue = editAfterData,
                            Operate = it.DiffType.GetDescription()
                        };
                        db.Insertable(sysAudits).ExecuteCommandAsync();
                    }
                };
                //慢查询监测
                db.Aop.OnLogExecuted = (sql, pars) =>
                {
                    if (App.Configuration["Serilog:SqlExecutionTimeToMySQL"] == "true")
                    {
                        if (db.Ado.SqlExecutionTime.TotalSeconds > App.Configuration["Serilog:SqlExecutionTime"].ToDouble())
                        {
                            var parsJson = "";
                            var parsList = pars.Select(x => x.Value).ToList();
                            if (parsList != null && parsList.Count() > 0)
                            {
                                parsJson = db.Utilities.SerializeObject(parsList);
                            }
                            App.ServiceProvider.GetService<ILogger>().Warning(Oops.Oh(SystemErrorCodes.s2405, $"{sql} 参数:{parsJson}").Message);
                        }
                    }
                };
            });

            // 注册拦截器
            services.AddScoped<LogHandler>();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseUnifyResultStatusCodes();

            app.UseHttpsRedirection();

            app.UseStaticFiles();

            app.UseSerilogRequestLogging(options => {
                options.MessageTemplate = "{RequestMethod} {RequestPath} responsed {StatusCode} in {Elapsed} ms, {RequestHost}, {ContentType}, Ip {OperIp}, Os {OperOs}, Browser {OperBrowser}";

                options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
                {
                    diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
                    diagnosticContext.Set("ContentType", httpContext.Response.ContentType);
                    diagnosticContext.Set("OperIp", NetHelper.Ip);
                    diagnosticContext.Set("OperOs", NetHelper.GetOSVersion());
                    diagnosticContext.Set("OperBrowser", NetHelper.Browser);
                };
            });

            app.UseRouting();

            app.UseCorsAccessor();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseInject(string.Empty);

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}